package com.bincloud.vue.admin.web.service.api.impl;

import com.bincloud.vue.admin.common.constanst.RedisConstant;
import com.bincloud.vue.admin.common.exception.BaseException;
import com.bincloud.vue.admin.common.exception.CodeMsg;
import com.bincloud.vue.admin.common.util.CaptchaUtils;
import com.bincloud.vue.admin.common.util.ObjectUtils;
import com.bincloud.vue.admin.web.service.api.CaptchaService;
import com.bincloud.vue.admin.web.util.config.CaptchaConfig;
import com.bincloud.vue.admin.web.util.redis.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @Description: 验证码相关接口实现
 * @Author: bincloud, mvpzhou
 * @Date: Create By bincloud, mvpzhou on 2022/2/24
 */
@Service
@Slf4j
public class CaptchaServiceImpl implements CaptchaService {
    @Resource
    private CaptchaConfig captchaConfig;
    @Resource
    private RedisService redisService;

    /**
     * 获取图形验证码
     *
     * @param username 用户名
     * @return 图形验证码 Base64String
     */
    @Override
    public String captcha(String username) {
        // 获取生成验证码
        CaptchaUtils.Captcha captcha = CaptchaUtils.captcha(captchaConfig.getType());
        String key = RedisConstant.CAPTCHA + username;
        redisService.set(key, captcha.getCode(), captchaConfig.getTimeout());
        log.info("获取双因子验证码:{}", captcha.getCode());
        return captcha.getImgStr();
    }

    /**
     * 验证图形验证码
     *
     * @param username 用户名
     * @param code 验证码 当前
     * @apiNote 是否验证成功
     */
    @Override
    public boolean validate(String username, String code) {
        String key = RedisConstant.CAPTCHA + username;
        Object value = redisService.get(key);
        if (ObjectUtils.isNull(value)) {
            throw new BaseException(CodeMsg.CAPTCHA_EXPIRED);
        }
        if (!CaptchaUtils.validateCaptcha((String) value, code, captchaConfig.isIgnore())) {
            throw new BaseException(CodeMsg.CAPTCHA_ERROR);
        }
        return true;
    }

    /**
     * 获取双因子验证码
     *
     * @param username 用户名
     * @param token 凭证
     * @return 返参
     */
    @Override
    public boolean twoFactor(String username, String token) {
        // 获取生成验证码
        String tempKey = RedisConstant.TEMPORARY_USER_CACHE + username;
        Object temp = redisService.get(tempKey);
        if (ObjectUtils.isEmpty(temp)) {
            throw new BaseException(CodeMsg.CAPTCHA_TWO_FACTOR_EXPIRED);
        }
        String value = (String) temp;
        if (!CaptchaUtils.validateCaptcha(value, token, captchaConfig.isIgnore())) {
            throw new BaseException(CodeMsg.CAPTCHA_TWO_FACTOR_ERROR);
        }
        String key = RedisConstant.TWO_FACTOR_CAPTCHA + username;
        String captcha = CaptchaUtils.letter(0, 10);
        log.info("获取双因子验证码:{}", captcha);
        redisService.set(key, captcha, captchaConfig.getTimeout());
        return true;
    }
}
